package self.zhangkang.chart.service.index

import self.zhangkang.chart.data.KLineInfo
import self.zhangkang.chart.data.PriceMA
import self.zhangkang.chart.data.VolumeMA

/**
 * @author : Android-张康
 * created on: 2023/8/23 10:23
 * description:
 *
 * @param N N日的移动平均值
 */
class MATools(private val N: Int) {

    companion object {

        //MA参数
        private const val MA_5 = 5
        private const val MA_10 = 10
        private const val MA_20 = 20
        private const val MA_60 = 60

        fun calculationPriceMA(dataList: MutableList<KLineInfo>) {
            val ma5Tools = MATools(MA_5)
            val ma10Tools = MATools(MA_10)
            val ma20Tools = MATools(MA_20)
            val ma60Tools = MATools(MA_60)
            val getValue = { kLineInfo: KLineInfo ->
                kLineInfo.closePrice
            }
            dataList.forEachIndexed { index, kLineInfo ->
                val ma5 = ma5Tools.calculateMovingAverage(dataList, index, getValue = getValue)
                val ma10 = ma10Tools.calculateMovingAverage(dataList, index, getValue = getValue)
                val ma20 = ma20Tools.calculateMovingAverage(dataList, index, getValue = getValue)
                val ma60 = ma60Tools.calculateMovingAverage(dataList, index, getValue = getValue)
                dataList[index] = kLineInfo.copy(priceMA = PriceMA(ma5, ma10, ma20, ma60))
            }
        }

        fun calculationVolumeMA(dataList: MutableList<KLineInfo>) {
            val ma5Tools = MATools(MA_5)
            val ma10Tools = MATools(MA_10)
            val getValue: (KLineInfo) -> Long = { kLineInfo: KLineInfo ->
                kLineInfo.volume
            }
            dataList.forEachIndexed { index, kLineInfo ->
                val ma5 = ma5Tools.calculateMovingAverage(dataList, index, getValue = getValue)
                val ma10 = ma10Tools.calculateMovingAverage(dataList, index, getValue = getValue)
                dataList[index] = kLineInfo.copy(volumeMA = VolumeMA(ma5, ma10))
            }
        }
    }

    /**
     * 计算移动平均值
     *
     * @param dataList K线数据列表
     * @param currentIndex 当前的位置
     *
     * @return 返回 [currentIndex] 位置的 [N] 日移动平均值
     */
    fun <T> calculateMovingAverage(
        dataList: List<T>,
        currentIndex: Int,
        getValue: (T) -> Float
    ): Float {
        if (currentIndex + 1 < N) {
            return Float.NaN
        }
        var value: Float = getValue(dataList[currentIndex])
        for (index in currentIndex - N + 1 until currentIndex) {
            value += getValue(dataList[index])
        }
        return value.div(N)
    }

    /**
     * 计算移动平均值
     *
     * @param dataList K线数据列表
     * @param currentIndex 当前的位置
     *
     * @return 返回 [currentIndex] 位置的 [N] 日移动平均值
     */
    fun <T> calculateMovingAverage(
        dataList: List<T>,
        currentIndex: Int,
        getValue: (T) -> Long
    ): Long {
        if (currentIndex + 1 < N) {
            return Long.MIN_VALUE
        }
        var value: Long = getValue(dataList[currentIndex])
        for (index in currentIndex - N + 1 until currentIndex) {
            value += getValue(dataList[index])
        }
        return value.div(N)
    }
}